<html>
  <head>
	  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>i5ting_ztree_toc:node基础_day4</title>
		<link href="toc/style/github-bf51422f4bb36427d391e4b75a1daa083c2d840e.css" media="all" rel="stylesheet" type="text/css"/>
		<link href="toc/style/github2-d731afd4f624c99a4b19ad69f3083cd6d02b81d5.css" media="all" rel="stylesheet" type="text/css"/>
		<link href="toc/css/zTreeStyle/zTreeStyle.css" media="all" rel="stylesheet" type="text/css"/>
	  <style>
		pre {
		    counter-reset: line-numbering;
		    border: solid 1px #d9d9d9;
		    border-radius: 0;
		    background: #fff;
		    padding: 0;
		    line-height: 23px;
		    margin-bottom: 30px;
		    white-space: pre;
		    overflow-x: auto;
		    word-break: inherit;
		    word-wrap: inherit;
		}

		pre a::before {
		  content: counter(line-numbering);
		  counter-increment: line-numbering;
		  padding-right: 1em; /* space after numbers */
		  width: 25px;
		  text-align: right;
		  opacity: 0.7;
		  display: inline-block;
		  color: #aaa;
		  background: #eee;
		  margin-right: 16px;
		  padding: 2px 10px;
		  font-size: 13px;
		  -webkit-touch-callout: none;
		  -webkit-user-select: none;
		  -khtml-user-select: none;
		  -moz-user-select: none;
		  -ms-user-select: none;
		  user-select: none;
		}

		pre a:first-of-type::before {
		  padding-top: 10px;
		}

		pre a:last-of-type::before {
		  padding-bottom: 10px;
		}

		pre a:only-of-type::before {
		  padding: 10px;
		}

		.highlight { background-color: #ffffcc } /* RIGHT */
		</style>
  </head>
  <body>
	  <div>
				<div style='width:25%;'>
						<ul id="tree" class="ztree" style='width:100%'>

						</ul>
				</div>
        <div id='readme' style='width:70%;margin-left:20%;'>
          	<article class='markdown-body'>
            	<h1 id="node-js-day4">Node.js - day4</h1>
<h2 id="-">今天主要内容</h2>
<ol>
<li>获取参数的几种形式</li>
<li>了解web开发模式</li>
<li>设计数据库和后台接口</li>
<li>实现前端功能</li>
</ol>
<h2 id="1-express-">1. express中获取参数的几种形式</h2>
<p>回顾querystring将参数转换成对象</p>
<pre><code>服务器端： 
const  express=require(&quot;express&quot;);
const  app=express();
const querystring = require(&#39;querystring&#39;);
app.use((req,res,next)=&gt;{
    let  str=&quot;&quot;;
    req.on(&quot;data&quot;,(data)=&gt;{
        str+=data;
    });
    req.on(&quot;end&quot;,()=&gt;{
        //console.log(str);
        console.log(querystring.parse(str));
        req.body=querystring.parse(str);
        next();
    })
});
app.get(&quot;/&quot;,(req,res)=&gt;{
    res.sendFile(&quot;./views/index.html&quot;,{root:__dirname});
});
app.post(&quot;/query&quot;,(req,res)=&gt;{
    res.send(req.body);
});
app.listen(1500,()=&gt;{
     console.log(&#39;server running at http://127.0.0.1:1500&#39;) ;
});
</code></pre><ol>
<li><p><strong>获取 <code>http://127.0.0.1:3001/user?id=10&amp;name=zs</code> 中的查询参数：</strong></p>
<ul>
<li><p>直接使用 <code>req.query</code> 获取参数即可；</p>
</li>
<li><p>注意：URL 地址栏中通过 <code>查询字符串</code> 传递的参数，express 框架会直接解析，大家只需要使用 <code>req.query</code> 直接获取 URL 中 查询字符串的参数；</p>
<pre><code>服务器端：
const  express= require(&quot;express&quot;);
const  app=express();
app.get(&quot;/user&quot;,(req,res)=&gt;{
    console.log(req.query);
    res.send(&quot;ok&quot;);
});
app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
浏览器：http://127.0.0.1:2100/user?id=1
服务器返回值=========    { id: &#39;1&#39; }
</code></pre><p>​</p>
</li>
</ul>
</li>
<li><p><strong>从URL地址中获取路径参数：</strong></p>
<ul>
<li><p>假设后台的路由是 <code>app.get(&#39;/user/:id/:name&#39;, (req, res) =&gt; {})</code></p>
</li>
<li><p>假设客户端浏览器请求的URL地址为：<code>http://127.0.0.1:3001/user/10/zs</code></p>
</li>
<li><p>直接使用 <code>req.params</code> 可以获取URL地址中传递过来的参数；</p>
<pre><code>服务器端：
const  express= require(&quot;express&quot;);
const  app=express();

app.get(&quot;/aa/:id/:name&quot;,(req,res)=&gt;{
    console.log(req.params);
    res.send(&quot;ok&quot;);
});
app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
浏览器端：http://127.0.0.1:2100/aa/2/张三
服务器返回值：  ======  { id: &#39;2&#39;, name: &#39;张三&#39; }   
</code></pre><p>get传参总结：</p>
<p><a href="http://127.0.0.1:2100/user?id=1========req.query()">http://127.0.0.1:2100/user?id=1========req.query()</a>  获取==={ id: &#39;1&#39; }</p>
<p><a href="http://127.0.0.1:2100/aa/2/张三========req.params()">http://127.0.0.1:2100/aa/2/张三========req.params()</a> 获取==={ id: &#39;2&#39;, name: &#39;张三&#39; }</p>
</li>
</ul>
</li>
<li><strong>从post表单中获取提交的数据：</strong><ul>
<li>借助于<code>body-parser</code>来解析表单数据</li>
<li><strong>安装：</strong><code>npm i body-parser -S</code></li>
<li><strong>导入：</strong><code>const bodyParser = require(&#39;body-parser&#39;)</code></li>
<li><strong>注册中间件：</strong><code>app.use(bodyParser.urlencoded({ extended: false }))</code></li>
<li><strong>使用解析的数据：</strong> <code>req.body</code> 来访问解析出来的数据</li>
</ul>
</li>
</ol>
<pre><code>const  express= require(&quot;express&quot;);
const  app=express();
const bodyParser = require(&#39;body-parser&#39;)
app.use(bodyParser.urlencoded({ extended: false }))

app.use(express.static(&quot;./views&quot;));
=======/* get传参  使用req.query获取 */
app.get(&quot;/user&quot;,(req,res)=&gt;{
    console.log(req.query);
    res.send(&quot;ok&quot;);
});
======/* get传参  使用req.params */
app.get(&quot;/aa/:id/:name&quot;,(req,res)=&gt;{
    console.log(req.params);
    res.send(&quot;ok&quot;);
});
======/*  post传参  使用req.body   但是需要引入 body-parser*/ 
app.post(&quot;/user&quot;,(req,res)=&gt;{
    console.log(req.body);
    res.send(&quot;ok&quot;);
});
app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
</code></pre><h2 id="2-web-">2. Web 开发模式</h2>
<h3 id="2-1-">2.1 混合模式（传统开发模式）</h3>
<ul>
<li>以后端程序员为主，基本上不需要前端程序员，或者，前端程序员只负责画页面、美化样式、写JS特效，前端程序员不需要进行数据的交互；</li>
<li>这种开发模式，在早些年比较常见；</li>
<li>传统开发模式下，用的最多的是 Jquery + 模板引擎 + Bootstrap</li>
<li>后端页面 .php   .jsp   .aspx   .cshtml<h3 id="2-2-">2.2 前后端分离（趋势）</h3>
</li>
<li>后端负责操作数据库、给前端暴露接口</li>
<li>前后端分离的好处：保证了各个岗位的职责单一；</li>
<li>前端负责调用接口，渲染页面、前端就可以使用一些流行的前端框架 Vue， React， Angular</li>
</ul>
<h2 id="3-">3. 需求分析</h2>
<ol>
<li>后端项目运行地址：<a href="http://127.0.0.1:5000">http://127.0.0.1:5000</a></li>
<li>前端项目运行地址：<a href="http://127.0.0.1:3000">http://127.0.0.1:3000</a></li>
<li>前后端分离开发模式的注意点：<ul>
<li>跨域问题</li>
<li>如果不考虑 表单的 Post 提交，则 可以使用 JSONP 的形式来请求接口</li>
<li>但是，我们的项目中，涉及到了 英雄表单的 提交，表单提交一般都是Post</li>
<li>经过分析，由于JSONP，不支持Post，所以，我们的后端接口，无法设计成JSONP的接口；</li>
<li>前端项目 Jquery + 模板引擎 + Semantic UI</li>
</ul>
</li>
</ol>
<h2 id="4-jsonp-cors-">4. JSONP 和 CORS 的区别</h2>
<ol>
<li>JSONP的原理：动态创建script标签；<ul>
<li>JSONP发送的不是Ajax请求</li>
<li>不支持 Post 请求；</li>
</ul>
</li>
<li>CORS中文意思是<code>跨域资源共享</code> ,需要服务器端进行 <code>CORS</code> 配置；<ul>
<li>CORS 发送的是真正的Ajax请求</li>
<li>CORS 支持Ajax的跨域</li>
<li>如果要启用 CORS 跨域资源共享，关键在于 服务器端，只要 服务器支持CORS跨域资源共享，则 浏览器肯定能够正常访问 这种 CORS 接口；而且，客户端在 发送 Ajax的时候，就像发送普通AJax一样，没有任何代码上的变化；</li>
</ul>
</li>
<li>对于Node来说，如果想要开启 CORS 跨域通信，只需要安装<code>cors</code>的模块即可；</li>
</ol>
<h2 id="5-heros">5. 数据库设计 - heros</h2>
<table>
<thead>
<tr>
<th>字段名</th>
<th style="text-align:left">字段类型</th>
<th>字段描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td style="text-align:left">int</td>
<td>主键Id（自增）</td>
</tr>
<tr>
<td>name</td>
<td style="text-align:left">varchar</td>
<td>英雄名称</td>
</tr>
<tr>
<td>gender</td>
<td style="text-align:left">varchar</td>
<td>性别</td>
</tr>
<tr>
<td>ctime</td>
<td style="text-align:left">varchar</td>
<td>创建时间</td>
</tr>
<tr>
<td>isdel</td>
<td style="text-align:left">tinyint（布尔值）</td>
<td>是否被删除 0 表示未删除；1 表示已经被删除</td>
</tr>
</tbody>
</table>
<p>在 mysql 中的 tinyint 等同于 bool 值 </p>
<h2 id="6-">6. 后台接口设计</h2>
<pre><code>const  express= require(&quot;express&quot;);
const  app=express();

const  mysql=require(&quot;mysql&quot;);
const  conn=mysql.createConnection({
    host:&quot;localhost&quot;,
    user:&quot;root&quot;,
    password:&quot;root&quot;,
    database:&quot;node_001&quot;
});
app.get(&quot;/&quot;,(req,res)=&gt;{
    res.send(&quot;请求后台API接口成功！&quot;);

});
app.get(&quot;/getallhero&quot;,(req,res)=&gt;{
    const  sql=&quot;select  *  from  heros&quot;;
    conn.query(sql,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
        res.send({status:200,message:&quot;查询失败&quot;,data:result});
    });
});

app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
</code></pre><h3 id="-">获取所有英雄列表</h3>
<ul>
<li><p>请求类型：GET</p>
</li>
<li><p>请求地址：<code>http://127.0.0.1:5001/getallhero</code></p>
</li>
<li><p>请求的参数：无</p>
<pre><code>/* 获取所有英雄接口 */
app.get(&quot;/getallhero&quot;,(req,res)=&gt;{
    const  sql=&quot;select  *  from  heros&quot;;
    conn.query(sql,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
        res.send({status:200,message:&quot;查询成功&quot;,data:result});
    });
});
</code></pre><p>​</p>
</li>
</ul>
<h3 id="-">插入新的英雄数据</h3>
<ul>
<li><p>请求类型：POST</p>
</li>
<li><p>请求地址：<code>http://127.0.0.1:5001/addhero</code></p>
</li>
<li><p>请求参数：{ name, gender }</p>
<pre><code>1、padStart() 和 padEnd() 的使用
padStart()和padEnd()两个参数：1.添加完毕后的总长度2.添加的内容
padStart()：在前面添加  padEnd()在后面添加
</code></pre></li>
</ul>
<p><img  src="./pad.png"></p>
<pre><code>模拟post请求服务器端：
const  express= require(&quot;express&quot;);
const  app=express();

app.use(express.static(&quot;./views&quot;));
const  bodyParser=require(&quot;body-parser&quot;);
app.use(bodyParser.urlencoded({extended:false}));

const  mysql=require(&quot;mysql&quot;);
const  conn=mysql.createConnection({
    host:&quot;localhost&quot;,
    user:&quot;root&quot;,
    password:&quot;root&quot;,
    database:&quot;node_001&quot;
});
app.get(&quot;/&quot;,(req,res)=&gt;{
    res.send(&quot;请求后台API接口成功！&quot;);

});

/* 添加英雄接口 */
app.post(&quot;/addhero&quot;,(req,res)=&gt;{
    const  hero=req.body;
    const  dt=new  Date();
    const  y=dt.getFullYear();
    const  m=(dt.getMonth()+1).toString().padStart(2,&quot;0&quot;);
    const  d=dt.getDate().toString().padStart(2,&quot;0&quot;);

    const  hh=dt.getHours().toString().padStart(2,&quot;0&quot;);
    const  mm=dt.getMinutes().toString().padStart(2,&quot;0&quot;);
    const  ss=dt.getSeconds().toString().padStart(2,&quot;0&quot;);

    hero.ctime=y+&quot;-&quot;+m+&quot;-&quot;+d+&quot; &quot;+hh+&quot;:&quot;+mm+&quot;:&quot;+ss;
   console.log(hero);

   const  sql=&quot;insert  into  heros set ?&quot;
   conn.query(sql,hero,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:err.message,data:null});
        res.send({status:200,message:&quot;添加成功&quot;,data:null});
   }); 
});

app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
</code></pre><pre><code>模拟post请求客户端：
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;/addhero&quot; method=&quot;POST&quot;&gt;
    姓名:&lt;input type=&quot;text&quot; name=&quot;name&quot;&gt;
    年龄:&lt;input type=&quot;text&quot; name=&quot;age&quot;&gt;
    性别:&lt;select name=&quot;gender&quot;&gt;
        &lt;option value=&quot;男&quot;&gt;男&lt;/option&gt;
        &lt;option value=&quot;女&quot;&gt;女&lt;/option&gt;
    &lt;/select&gt;
    删除:  是：&lt;input type=&quot;radio&quot; name=&quot;isdel&quot; value=&quot;1&quot;&gt;
    否：&lt;input type=&quot;radio&quot; name=&quot;isdel&quot; value=&quot;0&quot;&gt;
    &lt;input type=&quot;submit&quot; value=&quot;提交&quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><h3 id="-id-">根据Id获取英雄信息</h3>
<p>请求类型：GET</p>
<p>请求地址：<code>http://127.0.0.1:5001/gethero/:id</code></p>
<p>请求参数：通过 URL 地址，把要查询的英雄Id，携带过去</p>
<pre><code>/* 根据id获取用户信息 */
app.get(&quot;/gethero/:id&quot;,(req,res)=&gt;{
    const sql=&quot;select  *  from  heros  where  id=?&quot;;
    const id=req.params.id;
    conn.query(sql,id,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
        res.send({status:200,message:&quot;查询成功&quot;,data:result});
    })
})
</code></pre><h3 id="-id-">根据Id更新英雄数据</h3>
<p>请求类型： POST</p>
<p>请求地址：<code>http://127.0.0.1:5001/updatehero/:id</code></p>
<p>请求参数：{ name, gender }</p>
<pre><code>模拟英雄更新post请求 服务端
/* 根据id更新英雄信息 */
app.post(&quot;/updatehero/:id&quot;,(req,res)=&gt;{

    const sql=&quot;update  heros set ?  where  id=?&quot;;
    const id=req.params.id;
    const newInfo=req.body;
    conn.query(sql,[newInfo,id],(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;更新失败&quot;,data:null});
        res.send({status:200,message:&quot;更新成功&quot;,data:result});
    });
});
</code></pre><pre><code>模拟英雄更新post请求  客户端
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form action=&quot;/updatehero/8&quot; method=&quot;POST&quot;&gt;
    姓名:&lt;input type=&quot;text&quot; name=&quot;name&quot;&gt;
    年龄:&lt;input type=&quot;text&quot; name=&quot;age&quot;&gt;
    性别:&lt;select name=&quot;gender&quot;&gt;
        &lt;option value=&quot;男&quot;&gt;男&lt;/option&gt;
        &lt;option value=&quot;女&quot;&gt;女&lt;/option&gt;
    &lt;/select&gt;
    删除:  
        是：&lt;input type=&quot;radio&quot; name=&quot;isdel&quot; value=&quot;1&quot;&gt;
        否：&lt;input type=&quot;radio&quot; name=&quot;isdel&quot; value=&quot;0&quot;&gt;
    &lt;input type=&quot;submit&quot; value=&quot;提交&quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><h3 id="-id-">根据Id软删除英雄数据</h3>
<p>请求类型：GET</p>
<p>请求地址：<code>http://127.0.0.1:5001/deletehero/:id</code></p>
<p>请求参数：通过 URL 地址栏传参，把 要删除的英雄Id提交给服务器</p>
<pre><code>/* 根据id软删除英雄信息 */
app.get(&quot;/deletehero/:id&quot;,(req,res)=&gt;{
    const sql=&quot;update heros  set isdel=0 where id=?&quot;;
    const id=req.params.id;
    conn.query(sql,id,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;软删除失败&quot;,data:null});
        res.send({status:200,message:&quot;软删除成功&quot;,data:result});
    })
})
</code></pre><h3 id="router-">router实现接口的调用</h3>
<pre><code>1、server.js
const  express= require(&quot;express&quot;);
const  app=express();

app.use(express.static(&quot;./views&quot;));
const  bodyParser=require(&quot;body-parser&quot;);
app.use(bodyParser.urlencoded({extended:false}));

const  router=require(&quot;./router.js&quot;);
app.use(router);

app.listen(2100,()=&gt;{
    console.log(&#39;server running at http://127.0.0.1:2100&#39;) 
});
</code></pre><pre><code>2、router.js  (需要引入express+mysql+数据库连接)
const  express= require(&quot;express&quot;);
const  router=express.Router();

const  mysql=require(&quot;mysql&quot;);
const  conn=mysql.createConnection({
    host:&quot;localhost&quot;,
    user:&quot;root&quot;,
    password:&quot;root&quot;,
    database:&quot;node_001&quot;
});

router.get(&quot;/&quot;,(req,res)=&gt;{
    res.send(&quot;请求后台API接口成功！&quot;);

});
/* 获取所有英雄接口 */
router.get(&quot;/getallhero&quot;,(req,res)=&gt;{
    const  sql=&quot;select  *  from  heros&quot;;
    conn.query(sql,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
        res.send({status:200,message:&quot;查询成功&quot;,data:result});
    });
});

/* 添加英雄接口 */
router.post(&quot;/addhero&quot;,(req,res)=&gt;{
    // const  sql=&quot;select  *  from  heros&quot;;
    // conn.query(sql,(err,result)=&gt;{
    //     if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
    //     res.send({status:200,message:&quot;查询失败&quot;,data:result});
    // });
    const  hero=req.body;
    const  dt=new  Date();
    const  y=dt.getFullYear();
    const  m=(dt.getMonth()+1).toString().padStart(2,&quot;0&quot;);
    const  d=dt.getDate().toString().padStart(2,&quot;0&quot;);

    const  hh=dt.getHours().toString().padStart(2,&quot;0&quot;);
    const  mm=dt.getMinutes().toString().padStart(2,&quot;0&quot;);
    const  ss=dt.getSeconds().toString().padStart(2,&quot;0&quot;);

    hero.ctime=y+&quot;-&quot;+m+&quot;-&quot;+d+&quot; &quot;+hh+&quot;:&quot;+mm+&quot;:&quot;+ss;
   console.log(hero);

   const  sql=&quot;insert  into  heros set ?&quot;
   conn.query(sql,hero,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:err.message,data:null});
        res.send({status:200,message:&quot;添加成功&quot;,data:null});
   }); 
});

/* 根据id获取用户信息 */
router.get(&quot;/gethero/:id&quot;,(req,res)=&gt;{
    const sql=&quot;select  *  from  heros  where  id=?&quot;;
    const id=req.params.id;
    conn.query(sql,id,(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;查询失败&quot;,data:null});
        res.send({status:200,message:&quot;查询成功&quot;,data:result});
    })
})

/* 根据id更新英雄信息 */
router.post(&quot;/updatehero/:id&quot;,(req,res)=&gt;{

    const sql=&quot;update  heros set ?  where  id=?&quot;;
    const id=req.params.id;
    const newInfo=req.body;
    conn.query(sql,[newInfo,id],(err,result)=&gt;{
        if(err) return  res.send({status:500,message:&quot;更新失败&quot;,data:null});
        res.send({status:200,message:&quot;更新成功&quot;,data:result});
    });
});

/* 根据id软删除英雄信息 */
router.get(&quot;/deletehero/:id&quot;,(req,res)=&gt;{
    const sql=&quot;update heros  set isdel=1 where id=?&quot;;
    const id=req.params.id;
    conn.query(sql,id,(err,result)=&gt;{
        console.log(sql);

        if(err) return  res.send({status:500,message:&quot;软删除失败&quot;,data:null});
        res.send({status:200,message:&quot;软删除成功&quot;,data:result});
    });
});

module.exports=router;
</code></pre><h2 id="7-">7. 前端功能实现</h2>
<p>Semantic UI======<a href="https://semantic-ui.cn/">https://semantic-ui.cn/</a></p>
<p><a href="https://semantic-ui.qyears.com/introduction/getting-started.php">https://semantic-ui.qyears.com/introduction/getting-started.php</a></p>
<pre><code>npm install -g gulp
npm install semantic-ui --save
cd semantic/
gulp build

注意：semantic-ui如果安装不成功直接在github上去下载然后在引入文件包，导致下载不成功原因：因为需要可能导致有部分安装不成功
</code></pre><p>semantic-ui在项目中的使用步骤：</p>
<h4 id="1-semantic">1、客户端 semantic</h4>
<pre><code>这里的客户端也是以服务器的形式打开：
&lt;h1&gt;说明：&lt;/h1&gt;
    1、客户端以服务器的形式打开，即客户端放在一个单独的服务器中
    2、前后分离demo，所以后端也会有自己的服务器
1、客户端文件   semantic
    1、创建服务器
    2、托管views  服务器开始就显示views中的index.html
    3、托管semantic ====方便views中的index.html可以引入semantic中的css+js文件
    4、安装jquery====semantic依赖于jquery
    5、托管node_modules====方便views中的index.html可以引入jquery

    客户端服务器文件  web.js
    const  express=require(&quot;express&quot;);
    const  path=require(&quot;path&quot;);
    const  app=express();
    app.use(express.static(&quot;./views&quot;));
    app.use(&quot;/semantic&quot;,express.static(&quot;./semantic&quot;));
    app.use(&quot;/node_modules&quot;,express.static(&quot;./node_modules&quot;));
    app.listen(3001,()=&gt;{
        console.log(&quot;http://127.0.0.1:3001&quot;);
    });
</code></pre><pre><code>2、客户端文件：views下的index.html========注意路径的引入都是绝对路径
模块使用：https://semantic-ui.com/introduction/getting-started.html
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;

    &lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;/semantic/dist/semantic.min.css&quot;&gt;
    &lt;script type=”text/javascript” src=&quot;/node_modules/jquery/dist/jquery.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=”text/javascript” src=&quot;/semantic/dist/semantic.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;英雄列表&lt;/h1&gt;
    &lt;button class=&quot;ui primary button&quot;&gt;Save &lt;/button&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><h4 id="2-api_server">2、接口服务器端  api_server</h4>
<pre><code>1、服务器端文件：  api_server
接口文件：服务器端server.js文件
const  express=require(&quot;express&quot;);
const  app=express();

/* 注册中间件 */
const  bodyParser=require(&quot;body-parser&quot;);
app.use(bodyParser.urlencoded({extended:false}));
/* 解决跨域 */
const  cors=require(&quot;cors&quot;);
app.use(cors());

/* 导入路由 */
const  router=require(&#39;./router.js&#39;);
app.use(router);

app.listen(5001,()=&gt;{
    console.log(&quot;http://127.0.0.1:5001&quot;);
})
</code></pre><pre><code>2、接口文件：服务器端router.js
const  express=require(&quot;express&quot;);
const  router=express.Router();

// router.get(&quot;/getHeroList&quot;,(req,res)=&gt;{
//     res.send(&quot;11111&quot;);
// })

const  crs=require(&quot;./controller.js&quot;);
router.get(&quot;/getHeroList&quot;,crs.getHeroList);
module.exports=router;
</code></pre><pre><code>3、接口文件：controller.js
const  conn=require(&quot;./db.js&quot;);
module.exports={
    &quot;getHeroList&quot;:(req,res)=&gt;{
        const  sql=&quot;select  *  from   heros&quot;;
        conn.query(sql,(err,result)=&gt;{
            if (err) return res.send({ status: 500, msg: err.message, data: null })
            // 如果获取数据成功，则直接返回成功的数据结果
            res.send({ status: 200, msg: &#39;ok&#39;, data: result })
        });
    }
}
</code></pre><pre><code>4、接口文件：db.js
const  mysql=require(&quot;mysql&quot;);
const conn=mysql.createConnection({
    host:&quot;localhost&quot;,
    user:&quot;root&quot;,
    password:&quot;root&quot;,
    database:&quot;node_001&quot;
});

module.exports = conn;
</code></pre><h4 id="3-art-template-semantic">3、art-template页面数据渲染    客户端：semantic</h4>
<p>表格渲染：<a href="https://semantic-ui.com/collections/table.html">https://semantic-ui.com/collections/table.html</a></p>
<pre><code>1、index.html
    说明：1、安装art-template并导入  2、引入js文件
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;ie=edge&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;/semantic/dist/semantic.min.css&quot;&gt;

    &lt;script src=&quot;/node_modules/jquery/dist/jquery.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;/semantic/dist/semantic.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;/node_modules/art-template/lib/template-web.js&quot;&gt;&lt;/script&gt;

    &lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;./index.css&quot;&gt;
    &lt;script src=&quot;./index.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;英雄列表&lt;/h1&gt;
    &lt;button class=&quot;ui primary button&quot; id=&quot;add&quot;&gt;添加英雄&lt;/button&gt;

    &lt;!-- 表格区域 --&gt;
    &lt;table class=&quot;ui celled striped red table&quot;&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th&gt;编号&lt;/th&gt;
                &lt;th&gt;英雄名称&lt;/th&gt;
                &lt;th&gt;性别&lt;/th&gt;
                &lt;th&gt;创建时间&lt;/th&gt;
                &lt;th&gt;操作&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody id=&quot;tbd&quot;&gt;
            &lt;!-- &lt;tr&gt;
                &lt;td data-label=&quot;Name&quot;&gt;James&lt;/td&gt;
                &lt;td data-label=&quot;Age&quot;&gt;24&lt;/td&gt;
                &lt;td data-label=&quot;Job&quot;&gt;Engineer&lt;/td&gt;
                &lt;td data-label=&quot;Job&quot;&gt;Engineer&lt;/td&gt;
                &lt;td data-label=&quot;Job&quot;&gt;Engineer&lt;/td&gt;
            &lt;/tr&gt; --&gt;

        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;/body&gt;
&lt;script type=&quot;text/templaye&quot; id=&quot;row&quot;&gt;
    {{each  data}}
        &lt;tr&gt;
            &lt;td data-label=&quot;Name&quot;&gt; 
                &lt;div class=&quot;ui ribbon label {{$value.isdel === 0 ? &#39;blue&#39; : &#39;red&#39;}}&quot;&gt;{{$value.isdel === 0 ? &#39;正常&#39; : &#39;删除&#39;}}&lt;/div&gt;
            &lt;/td&gt;
            &lt;td data-label=&quot;Age&quot;&gt;{{$value.name}}&lt;/td&gt;
            &lt;td data-label=&quot;Age&quot;&gt;{{$value.gender}}&lt;/td&gt;
            &lt;td data-label=&quot;Age&quot;&gt;{{$value.ctime}}&lt;/td&gt;
            &lt;td data-label=&quot;Age&quot;&gt;
                &lt;a&gt;编辑&lt;/a&gt;
                &lt;a&gt;删除&lt;/a&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    {{/each}}
&lt;/script&gt;
&lt;/html&gt;
</code></pre><pre><code>2、index.js
$(function() {
    function getHeroList(){
        $.ajax({
            type:&quot;get&quot;,
            url:&quot;http://127.0.0.1:5001/getHeroList&quot;,
            success:function(result){
                var  str=template(&quot;row&quot;,result);
                $(&#39;#tbd&#39;).html(str)
            }
        })
    };
    getHeroList();
})
</code></pre><h4 id="4-">4、添加英雄</h4>
<p>1、客户端：semantic</p>
<pre><code> semantic  =====index.html
$(function () {
    function getHeroList() {
        $.ajax({
            type: &quot;get&quot;,
            url: &quot;http://127.0.0.1:5001/getHeroList&quot;,
            success: function (result) {
                var str = template(&quot;row&quot;, result);
                $(&#39;#tbd&#39;).html(str)
            }
        })
    };
    getHeroList();

    /* 弹出层 */
    $(&#39;#add&#39;).on(&#39;click&#39;, function () {
        $(&#39;.ui.modal&#39;).modal(&#39;show&#39;)
    })
    // 初始化下拉框的样式
    $(&#39;.ui.dropdown&#39;).dropdown();

    $(&#39;#btnAdd&#39;).on(&#39;click&#39;, function () {
        $.ajax({
            type: &quot;post&quot;,
            url: &quot;http://127.0.0.1:5001/addhero&quot;,
            data: $(&quot;form&quot;).serialize(),
            success: function (result) {
                console.log(result,76);
            }
        });
    })
})
</code></pre><p>2、服务器端===api_server</p>
<pre><code>1、router.js
const conn = require(&quot;./db.js&quot;);
module.exports = {
    &quot;getHeroList&quot;: (req, res) =&gt; {
        const sql = &quot;select  *  from   heros&quot;;
        conn.query(sql, (err, result) =&gt; {
            if (err) return res.send({
                status: 500,
                msg: err.message,
                data: null
            })
            // 如果获取数据成功，则直接返回成功的数据结果
            res.send({
                status: 200,
                msg: &#39;ok&#39;,
                data: result
            })
        });
    },

    &quot;addhero&quot;: (req, res) =&gt; {
        const hero = req.body;
        const  dt=new  Date();
        const  y=dt.getFullYear();
        const  m=dt.getMonth().toString().padStart(2,&quot;0&quot;);
        const  d=dt.getDate().toString().padStart(2,&quot;0&quot;);

        const  hh=dt.getHours();
        const  mm=dt.getMinutes();
        const  ss=dt.getSeconds();
        hero.ctime=y+&quot;-&quot;+m+&quot;-&quot;+d+&quot;  &quot;+hh+&quot;:&quot;+mm+&quot;:&quot;+ss;
        const  sql=&quot;insert  into  heros  set  ?&quot;;
        conn.query(sql,hero,(err,result)=&gt;{
            if (err) return res.send({
                status: 500,
                msg: err.message,
                data: null
            })
            // 如果获取数据成功，则直接返回成功的数据结果
            res.send({
                status: 200,
                msg: &#39;ok&#39;,
                data: null
            })
        });
    }
}
</code></pre><pre><code>2、controller.js
const conn = require(&quot;./db.js&quot;);
module.exports = {
    &quot;getHeroList&quot;: (req, res) =&gt; {
        const sql = &quot;select  *  from   heros&quot;;
        conn.query(sql, (err, result) =&gt; {
            if (err) return res.send({
                status: 500,
                msg: err.message,
                data: null
            })
            // 如果获取数据成功，则直接返回成功的数据结果
            res.send({
                status: 200,
                msg: &#39;ok&#39;,
                data: result
            })
        });
    },

    &quot;addhero&quot;: (req, res) =&gt; {
        const hero = req.body;
        const  dt=new  Date();
        const  y=dt.getFullYear();
        const  m=dt.getMonth().toString().padStart(2,&quot;0&quot;);
        const  d=dt.getDate().toString().padStart(2,&quot;0&quot;);

        const  hh=dt.getHours();
        const  mm=dt.getMinutes();
        const  ss=dt.getSeconds();
        hero.ctime=y+&quot;-&quot;+m+&quot;-&quot;+d+&quot;  &quot;+hh+&quot;:&quot;+mm+&quot;:&quot;+ss;
        const  sql=&quot;insert  into  heros  set  ?&quot;;
        conn.query(sql,hero,(err,result)=&gt;{
            if (err) return res.send({
                status: 500,
                msg: err.message,
                data: null
            })
            // 如果获取数据成功，则直接返回成功的数据结果
            res.send({
                status: 200,
                msg: &#39;ok&#39;,
                data: null
            })
        });
    }
}
</code></pre><h2 id="-">相关文章</h2>
<ul>
<li><a href="http://www.ruanyifeng.com/blog/2016/04/cors.html">跨域资源共享 CORS 详解</a></li>
<li><a href="https://github.com/expressjs/cors">cors模块解决Node跨域资源共享问题</a></li>
</ul>

          	</article>
        </div>
		</div>
  </body>
</html>
<script type="text/javascript" src="toc/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="toc/js/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="toc/js/ztree_toc.js"></script>
<script type="text/javascript" src="toc_conf.js"></script>

<SCRIPT type="text/javascript" >
<!--
$(document).ready(function(){
    var css_conf = eval(markdown_panel_style);
    $('#readme').css(css_conf)
    
    var conf = eval(jquery_ztree_toc_opts);
		$('#tree').ztree_toc(conf);
});
//-->
</SCRIPT>